﻿using Ganjine;
using Ganjine.Common;
using Ganjine.DataModel;
using Ganjine_Windows10.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace Ganjine_Windows10
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class SectionPage : Page
    {
        private ObservableDictionary defaultViewModel = new ObservableDictionary();
        private int myid;
        DataBridge1 db;
        bool isNavigatedBack = false;
        int foldersCount = 0;

        public SectionPage()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Gets the DefaultViewModel. This can be changed to a strongly typed view model.
        /// </summary>
        public ObservableDictionary DefaultViewModel
        {
            get { return this.defaultViewModel; }
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (e.NavigationMode == NavigationMode.Back)
            {
                isNavigatedBack = true;
                Frame.ForwardStack.Clear();
            }

            db = Newtonsoft.Json.JsonConvert.DeserializeObject<DataBridge1>(e.Parameter.ToString());

            if (db.rootPath == null)
                db.rootPath = "";
            else if (db.rootPath.Length > 0)
                db.rootPath = "، " + db.rootPath;

            defaultViewModel["Title"] = db.title + db.rootPath;
            defaultViewModel["PoetImagePath"] = "Assets/" + db.poetid + ".jpg";

            if (db.isChildItem)
            {
                SearchTextBox.Visibility = Visibility.Collapsed;
                SearchButton.Visibility = Visibility.Collapsed;
                SearchToggle.Width = 0;
            }

            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            if ((e.NavigationMode == NavigationMode.New) || (e.NavigationMode == NavigationMode.Forward))
            {
                var gridViewSV = VisualChildFinder.FindVisualChild<ScrollViewer>(gridView);
                var listViewSV = VisualChildFinder.FindVisualChild<ScrollViewer>(listView);
                if (gridViewSV != null)
                    App.scrollPosition[headerText.Text + "Grid"] = gridViewSV.VerticalOffset;
                else
                    App.scrollPosition[headerText.Text + "Grid"] = 0;

                if (listViewSV != null)
                    App.scrollPosition[headerText.Text + "List"] = listViewSV.VerticalOffset;
                else
                    App.scrollPosition[headerText.Text + "List"] = 0;
            }
            else
            {
                App.scrollPosition[headerText.Text + "Grid"] = 0;
                App.scrollPosition[headerText.Text + "List"] = 0;
            }

            base.OnNavigatedFrom(e);
        }

        /// <summary>
        /// Invoked when an item is clicked.
        /// </summary>
        /// <param name="sender">The GridView displaying the item clicked.</param>
        /// <param name="e">Event data that describes the item clicked.</param>
        private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
        {
            ItemClick(e.ClickedItem);
        }

        private void ItemClick(object c, int optionalParentId = -1)
        {
            PoemItem poem = (PoemItem)(c);

            if (poem.Type == PoemItemType.Category)
            {
                DataBridge1 db = new DataBridge1()
                {
                    id = poem.ID,
                    title = poem.Text,
                    isChildItem = true,
                    rootPath = defaultViewModel["Title"].ToString()
                };
                Frame.Navigate(typeof(SectionPage), Newtonsoft.Json.JsonConvert.SerializeObject(db));
            }
            else
            {
                DataBridge2 db = new DataBridge2()
                {
                    parentid = (optionalParentId == -1) ? myid : optionalParentId,
                    id = poem.ID,
                    title = poem.Text
                };
                Frame.Navigate(typeof(ItemPage), Newtonsoft.Json.JsonConvert.SerializeObject(db));

            }


            /* var itemId = ((SampleDataItem)e.ClickedItem).UniqueId;
             if (!Frame.Navigate(typeof(ItemPage), itemId))
             {
                 var resourceLoader = ResourceLoader.GetForCurrentView("Resources");
                 throw new Exception(resourceLoader.GetString("NavigationFailedExceptionMessage"));
             }*/
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            SetSearchButtonOpacity();

            List<PoemItem> l = new List<PoemItem>();

            int i = 0;

            //Avoid hanging UI while we're loading from database.
            await Task.Run(() =>
            {
                l.AddRange(App.dataSource.GetListOfChildren(db.id));
                foldersCount = l.Count;
                List<PoemItem> b = App.dataSource.GetListOfPoems(db.id);
                l.AddRange(b);
                i = b.Count;
            });

            foreach (var item in l)
            {
                if ((item.s1 != null) && (item.s1.Length > 75))
                    item.s2 = "";
            }

            myid = db.id;
            defaultViewModel["Items"] = l;

            if (i > 1)
            {
                JumpAppBarButton.Visibility = Visibility.Visible;
                JumpMaxNum.Text = i.ToString();
            }
            if ((i > 1) || ((l.Count - i) > 0))
                RandomAppBarButton.Visibility = Visibility.Visible;


            if (isNavigatedBack)
            {
                CorrectScrollPosition();
                await Task.Delay(50);
                CorrectScrollPosition();

                isNavigatedBack = false;
            }
        }

        private void CorrectScrollPosition()
        {
            var gridViewSV = VisualChildFinder.FindVisualChild<ScrollViewer>(gridView);
            var listViewSV = VisualChildFinder.FindVisualChild<ScrollViewer>(listView);

            if (gridViewSV != null)
                gridViewSV.ChangeView(gridViewSV.HorizontalOffset, App.scrollPosition[headerText.Text + "Grid"], gridViewSV.ZoomFactor, true);
            if (listViewSV != null)
                listViewSV.ChangeView(listViewSV.HorizontalOffset, App.scrollPosition[headerText.Text + "List"], listViewSV.ZoomFactor, true);
        }


        private void PhoneSearchHardwareBackButtonPressed(object sender, BackRequestedEventArgs e)
        {
            e.Handled = true;
            SearchBackToggle_Click(sender, new RoutedEventArgs());
        }

        private void SearchToggle_Click(object sender, RoutedEventArgs e)
        {
            headerText.Visibility = Visibility.Collapsed;
            SearchToggle.Visibility = Visibility.Collapsed;
            SearchBackToggle.Visibility = Visibility.Visible;
            SearchBar.Visibility = Visibility.Visible;

            SearchTextBox.Focus(FocusState.Pointer);
            PhoneItemView.Visibility = Visibility.Collapsed;
            PhoneCommandBar.Visibility = Visibility.Collapsed;

            SystemNavigationManager.GetForCurrentView().BackRequested += PhoneSearchHardwareBackButtonPressed;
        }

        private void SearchBackToggle_Click(object sender, RoutedEventArgs e)
        {
            headerText.Visibility = Visibility.Visible;
            SearchToggle.Visibility = Visibility.Visible;
            SearchBackToggle.Visibility = Visibility.Collapsed;
            SearchBar.Visibility = Visibility.Collapsed;

            SearchTextBox.Text = "";
            PhoneItemView.Visibility = Visibility.Visible;
            PhoneCommandBar.Visibility = Visibility.Visible;

            SystemNavigationManager.GetForCurrentView().BackRequested -= PhoneSearchHardwareBackButtonPressed;
        }

        private void ImageBrush_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            PoetImage.Width = 0;
        }

        private void BackToggle_Click(object sender, RoutedEventArgs e)
        {
            Frame.GoBack();
        }

        private void SearchButton_Click(object sender, RoutedEventArgs e)
        {
            if (SearchTextBox.Text.Length >= App._minSearchTextLength)
                Frame.Navigate(typeof(Search), Newtonsoft.Json.JsonConvert.SerializeObject(new DataBridgeSearch(SearchTextBox.Text, db.poetid)));
        }

        private void SearchTextBox_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == Windows.System.VirtualKey.Enter)
            {
                SearchButton_Click(sender, new RoutedEventArgs());
            }
        }


        private void KeyPress(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.CharacterReceivedEventArgs args)
        {
            if (FocusManager.GetFocusedElement() is TextBox)
                return;

            if ((SearchTextBox.FocusState == Windows.UI.Xaml.FocusState.Unfocused) &&
                (SearchBar.Visibility == Visibility.Visible))
            {
                Char c = Convert.ToChar(args.KeyCode);
                if (Char.IsLetterOrDigit(c))
                {
                    SearchTextBox.Text = c.ToString();
                    SearchTextBox.SelectionStart = SearchTextBox.Text.Length;
                    SearchTextBox.SelectionLength = 0;
                    SearchTextBox.Focus(FocusState.Programmatic);
                }
            }
        }

        private void KeyPressEventRegister()
        {
            if (SearchBar.Visibility == Visibility.Visible)
                Window.Current.CoreWindow.CharacterReceived += KeyPress;
            else
                Window.Current.CoreWindow.CharacterReceived -= KeyPress;
        }

        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            Window.Current.CoreWindow.CharacterReceived -= KeyPress;

            base.OnNavigatingFrom(e);
        }

        private void pageRoot_GotFocus(object sender, RoutedEventArgs e)
        {
            KeyPressEventRegister();
        }

        private void pageRoot_LostFocus(object sender, RoutedEventArgs e)
        {
            //Window.Current.CoreWindow.CharacterReceived -= KeyPress;
            //System.Diagnostics.Debug.WriteLine("LostFocus");
        }

        private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            KeyPressEventRegister();
        }

        private void SetSearchButtonOpacity()
        {
            SearchButton.Opacity = (SearchTextBox.Text.Length >= App._minSearchTextLength) ? 1 : 0.3;
        }

        private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            SetSearchButtonOpacity();
        }

        private void SearchTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if ((SearchBar.HorizontalAlignment == HorizontalAlignment.Stretch) &&
                (SearchButton.FocusState == FocusState.Unfocused))
                SearchBackToggle_Click(sender, e);
        }

        
        private async void RandomPoem_Click(object sender, RoutedEventArgs e)
        {
            LoadingRing.Visibility = Visibility.Visible;
            Header.Visibility = Visibility.Collapsed;
            TabletItemView.Visibility = Visibility.Collapsed;
            PhoneItemView.Visibility = Visibility.Collapsed;
            PhoneCommandBar.Visibility = Visibility.Collapsed;

            List<Tuple<PoemItem, int>> poems = new List<Tuple<PoemItem, int>>();
            var curItems = (List<PoemItem>)defaultViewModel["Items"];
            

            await Task.Run(() =>
            {
                AddPoemFolder(ref poems, ref curItems, myid);
            });


            Random r = new Random();
            var randomItem = poems[r.Next(0, poems.Count)];
            LoadingRing.Visibility = Visibility.Collapsed;
            ItemClick(randomItem.Item1, randomItem.Item2);
        }

        private void AddPoemFolder(ref List<Tuple<PoemItem, int>> OutputPoems, ref List<PoemItem> curItems, int parentid)
        {
            foreach (var item in curItems)
            {
                if (item.Type == PoemItemType.Poem)
                    OutputPoems.Add(new Tuple<PoemItem, int>(item, parentid));
                else
                {
                    List<PoemItem> l = App.dataSource.GetListOfChildren(item.ID);
                    l.AddRange(App.dataSource.GetListOfPoems(item.ID));

                    AddPoemFolder(ref OutputPoems, ref l, item.ID);
                }
            }
        }

        private async void JumpButton_Click(object sender, TappedRoutedEventArgs e)
        {
            int num;
            if (int.TryParse(JumpNumberTextBox.Text, out num))
            {
                if ((num >= 1) && (num <= int.Parse(JumpMaxNum.Text)))
                {
                    try
                    {
                        ItemClick(((List<PoemItem>)defaultViewModel["Items"])[int.Parse(JumpNumberTextBox.Text) - 1 + foldersCount]);
                        return;
                    }
                    catch
                    {

                    }
                }
            }
            var dialog = new MessageDialog("عدد وارد شده در محدوده‌ی مجاز نیست.");
            await dialog.ShowAsync();
        }

        private void JumpNumberTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            int num;
            if (int.TryParse(JumpNumberTextBox.Text, out num))
            {
                if ((num >= 1) && (num <= int.Parse(JumpMaxNum.Text)))
                {
                    JumpButton.IsEnabled = true;
                    JumpButton.Opacity = 1;
                    return;
                }
            }
            JumpButton.IsEnabled = false;
            JumpButton.Opacity = 0.8;
        }

        private void JumpAppBarButton_Click(object sender, RoutedEventArgs e)
        {
            JumpNumberTextBox.Text = "";
            JumpButton.Opacity = 0.8;
        }

        /*        private void AppBarRandomButton_Click(object sender, RoutedEventArgs e)
                {
                    Random r = new Random();
                    ItemClick(itemGridView.Items[r.Next(0, itemGridView.Items.Count - 1)]);
                }

                private void Grid_Tapped(object sender, TappedRoutedEventArgs e)
                {
                    appBar.IsOpen = true;
                }*/


    }
}
